﻿#pragma once

#include "../render/IType.h"
#include "../render/SColor.h"
#include "../render/SRender-i.h"
#include <memory>

namespace SOUI
{
    class SPen_GDI;
    class SFont_GDI;
    class SBrush_GDI;
    class SBitmap_GDI;
    class SRegion_GDI;
    class SRenderTarget_GDI;
    typedef std::shared_ptr<SPen_GDI> SPen_GDIPtr;
	typedef std::shared_ptr<SFont_GDI> SFont_GDIPtr;
    typedef std::shared_ptr<SBrush_GDI> SBrush_GDIPtr;
	typedef std::shared_ptr<SBitmap_GDI> SBitmap_GDIPtr;
    typedef std::shared_ptr< SRegion_GDI> SRegion_GDIPtr;
	typedef std::shared_ptr<SRenderTarget_GDI> SRenderTarget_GDIPtr;

    //////////////////////////////////////////////////////////////////////////
    // SRenderFactory_GDI
    class SRenderFactory_GDI : public IRenderFactory, public std::enable_shared_from_this<SRenderFactory_GDI>
    {
    public:
        SRenderFactory_GDI()
        {
        }

        ~SRenderFactory_GDI()
        {
        }
        
        virtual IImgDecoderFactoryPtr GetImgDecoderFactory(){return m_imgDecoderFactory;}
        virtual void SetImgDecoderFactory(IImgDecoderFactoryPtr pImgDecoderFac){ m_imgDecoderFactory=pImgDecoderFac;}
        virtual BOOL CreateRenderTarget(IRenderTargetPtr &ppRenderTarget,int nWid,int nHei);
        virtual BOOL CreateFont(IFontPtr &ppFont , const LOGFONT &lf);
        virtual BOOL CreateBitmap(IBitmapPtr &ppBitmap);
        virtual BOOL CreateRegion(IRegionPtr &ppRgn);

		virtual BOOL CreatePath(IPathPtr &ppPath);

		virtual BOOL CreatePathEffect(REFGUID guidEffect,IPathEffectPtr &ppPathEffect);
		
		virtual BOOL CreatePathMeasure(IPathMeasurePtr &ppPathMeasure);

		virtual HRESULT CreateBlurMaskFilter(float radius, IMaskFilter::SkBlurStyle style,IMaskFilter::SkBlurFlags flag,IMaskFilterPtr &ppMaskFilter){return E_NOTIMPL;}
		virtual HRESULT CreateEmbossMaskFilter(float direction[3], float ambient, float specular, float blurRadius,IMaskFilterPtr &ppMaskFilter){return E_NOTIMPL;}

    protected:
        IImgDecoderFactoryPtr m_imgDecoderFactory;
    };


    //////////////////////////////////////////////////////////////////////////
    // SPen_GDI
    class SPen_GDI : public IPen
    {
	public:
        SPen_GDI(IRenderFactoryPtr pRenderFac,int iStyle=PS_SOLID,COLORREF cr=0,int cWidth=1)
            :IPen(pRenderFac)
            ,m_nWidth(cWidth),m_style(iStyle),m_cr(cr)
            ,m_hPen(NULL)
        {
			if (iStyle & PS_GEOMETRIC)
			{
				LOGBRUSH lb;
				lb.lbStyle = BS_SOLID;
				lb.lbColor = m_cr & 0x00ffffff;
				lb.lbHatch = 0;
				m_hPen = ::ExtCreatePen(m_style | PS_GEOMETRIC, m_nWidth, &lb, 0, NULL);
			}
			else
			{
				m_hPen = ::CreatePen(m_style , m_nWidth, m_cr & 0x00ffffff);
			}
        }

        ~SPen_GDI()
        {
            DeleteObject(m_hPen);
        }

        int GetWidth(){return m_nWidth;}

        int GetStyle(){return m_style;}

        void SetWidth(int nWid) {m_nWidth=nWid;}

        COLORREF GetColor(){return m_cr;}

        void SetColor(COLORREF cr){m_cr = cr;}
        
        HPEN GetPen(){return m_hPen;}
    protected:

        int		m_style;
        int		m_nWidth;
        COLORREF	m_cr;
        
        HPEN    m_hPen;
    };

    //////////////////////////////////////////////////////////////////////////
    // SFont_GDI
    class SFont_GDI: public IFont
    {
    public:
        SFont_GDI(IRenderFactoryPtr pRenderFac,const LOGFONT * plf)
            :IFont(pRenderFac),m_hFont(NULL)
        {
            memcpy(&m_lf,plf,sizeof(LOGFONT));
            m_hFont=CreateFontIndirect(&m_lf);
        }
        ~SFont_GDI()
        {
            DeleteObject(m_hFont);
        }

        virtual const LOGFONT * LogFont() const {return &m_lf;}

        virtual LPCTSTR FamilyName()
        {
            return m_lf.lfFaceName;
        }
        virtual int TextSize(){return m_lf.lfHeight;}
        virtual BOOL IsBold(){ return m_lf.lfWeight == FW_BOLD;}
        virtual BOOL IsUnderline(){return m_lf.lfUnderline;}
        virtual BOOL IsItalic(){return m_lf.lfItalic;}
        virtual BOOL IsStrikeOut(){return m_lf.lfStrikeOut;}

		virtual BOOL UpdateFont(const LOGFONT *pLogFont)
		{
			if(!m_hFont) return FALSE;
			DeleteObject(m_hFont);
			memcpy(&m_lf,pLogFont,sizeof(LOGFONT));
			m_hFont = CreateFontIndirect(&m_lf);
			return TRUE;
		}

        HFONT GetFont(){return m_hFont;}
    protected:
        LOGFONT     m_lf;
        HFONT       m_hFont;
    };

    class SBrush_GDI : public IBrush
    {
    public:
        static SBrush_GDIPtr CreateSolidBrush(IRenderFactoryPtr pRenderFac,COLORREF cr){
            return std::make_shared<SBrush_GDI>(pRenderFac,cr);
        }

        static SBrush_GDIPtr CreateBitmapBrush(IRenderFactoryPtr pRenderFac,HBITMAP hBmp)
        {
            return std::make_shared<SBrush_GDI>(pRenderFac,hBmp);
        }


        BOOL IsBitmap(){return m_fBmp;}
        
        HBRUSH GetBrush(){return m_hBrush;}

        COLORREF GetColor() const {return m_cr;}

        SBrush_GDI(IRenderFactoryPtr pRenderFac,COLORREF cr)
            :IBrush(pRenderFac),m_fBmp(FALSE),m_cr(cr)
        {
            m_hBrush = ::CreateSolidBrush(m_cr&0x00ffffff);
        }
        SBrush_GDI(IRenderFactoryPtr pRenderFac,HBITMAP hBmp)
            :IBrush(pRenderFac),m_fBmp(TRUE)
        {
            m_hBrush = ::CreatePatternBrush(hBmp);
        }
        ~SBrush_GDI()
        {
            DeleteObject(m_hBrush);
        }


        HBRUSH   m_hBrush;
        BOOL	 m_fBmp;
        COLORREF    m_cr;
    };

    //////////////////////////////////////////////////////////////////////////
    // SBitmap_GDI
    class SBitmap_GDI :public IBitmap
    {
    public:
        SBitmap_GDI(IRenderFactoryPtr pRenderFac)
            :IBitmap(pRenderFac),m_hBmp(0)
        {
            m_sz.cx=m_sz.cy=0;
        }
        virtual ~SBitmap_GDI()
        {
            if(m_hBmp) DeleteObject(m_hBmp);
        }
        virtual HRESULT Init(int nWid,int nHei,const LPVOID pBits=NULL);
        virtual HRESULT Init(IImgFramePtr pFrame);
		virtual HRESULT LoadFromFile(LPCTSTR pszFileName);
        virtual HRESULT LoadFromMemory(LPBYTE pBuf,size_t szLen);

        virtual UINT Width() const;
        virtual UINT Height() const;
        virtual SIZE Size() const;
        virtual LPVOID  LockPixelBits();
        virtual void    UnlockPixelBits(LPVOID pBuf);
        virtual const LPVOID GetPixelBits() const;
        
        HBITMAP  GetBitmap(){return m_hBmp;}

        static HBITMAP CreateGDIBitmap(int nWid,int nHei,void ** ppBits);
    protected:

        HRESULT ImgFromDecoder(IImgXPtr imgDecoder);
        SIZE        m_sz;
        HBITMAP     m_hBmp;     //标准的32位位图，和m_bitmap共享内存
    };

    //////////////////////////////////////////////////////////////////////////
    //	SRegion_GDI
    class SRegion_GDI: public IRegion
    {
		friend class SRenderTarget_GDI;
    public:
        SRegion_GDI(IRenderFactoryPtr pRenderFac);
        ~SRegion_GDI(){
            DeleteObject(m_hRgn);
        }

        virtual void CombineRect(LPCRECT lprect,int nCombineMode);
		virtual void CombineRoundRect(LPCRECT lprect, POINT ptRadius, int nCombineMode);
		virtual void CombineEllipse(LPCRECT lprect , int nCombineMode);
		virtual void CombinePolygon(const POINT * pts, int count, int nPolygonMode, int nCombineMode);
		virtual void CombineRgn(const IRegionPtr pRgnSrc,int nCombineMode );

        virtual BOOL PtInRegion(POINT pt) const;
        virtual BOOL RectInRegion(LPCRECT lprect) const;
        virtual void GetRgnBox(LPRECT lprect) const;
        virtual BOOL IsEmpty() const;
        virtual void Offset(POINT pt);
        virtual void Clear();

		virtual BOOL IsEqual(const IRegionPtr testRgn) const;
    protected:
        HRGN GetRegion() const;
        void _CombineRgn(HRGN hRgn,int nCombineMode);



        HRGN    m_hRgn;
    };

    //////////////////////////////////////////////////////////////////////////
    //	SRenderTarget_GDI
    //////////////////////////////////////////////////////////////////////////
    class SRenderTarget_GDI: public IRenderTarget
    {
    public:
        SRenderTarget_GDI(IRenderFactoryPtr pRenderFactory,int nWid,int nHei);
        ~SRenderTarget_GDI();

        //只支持创建位图表面
        virtual HRESULT CreateCompatibleRenderTarget(SIZE szTarget,IRenderTargetPtr &ppRenderTarget);

        virtual HRESULT CreatePen(int iStyle,COLORREF cr,int cWidth,IPenPtr &ppPen);
        virtual HRESULT CreateSolidColorBrush(COLORREF cr,IBrushPtr &ppBrush);
        virtual HRESULT CreateBitmapBrush( IBitmapPtr pBmp,IBrushPtr &ppBrush );

        virtual HRESULT Resize(SIZE sz);

        virtual HRESULT OffsetViewportOrg(int xOff, int yOff, LPPOINT lpPoint=NULL);
        virtual HRESULT GetViewportOrg(LPPOINT lpPoint);
        virtual HRESULT SetViewportOrg(POINT pt);

        virtual HRESULT PushClipRect(LPCRECT pRect,UINT mode=RGN_AND);
        virtual HRESULT PushClipRegion(IRegionPtr pRegion,UINT mode=RGN_AND);
        virtual HRESULT PopClip();

        virtual HRESULT ExcludeClipRect(LPCRECT pRc);
        virtual HRESULT IntersectClipRect(LPCRECT pRc);

        virtual HRESULT SaveClip(int *pnState);
        virtual HRESULT RestoreClip(int nState=-1);

        virtual HRESULT GetClipRegion(IRegionPtr &ppRegion);
        virtual HRESULT GetClipBox(LPRECT prc);

        virtual HRESULT BitBlt(LPCRECT pRcDest,IRenderTargetPtr pRTSour,int xSrc,int ySrc,DWORD dwRop=SRCCOPY);
        virtual HRESULT AlphaBlend(LPCRECT pRcDest,IRenderTargetPtr pRTSrc,LPCRECT pRcSrc,BYTE byAlpha);

        virtual HRESULT DrawText( LPCTSTR pszText,int cchLen,LPRECT pRc,UINT uFormat);
        virtual HRESULT MeasureText(LPCTSTR pszText,int cchLen, SIZE *psz );

        virtual HRESULT DrawRectangle(LPCRECT pRect);
        virtual HRESULT FillRectangle(LPCRECT pRect);
        virtual HRESULT FillSolidRect(LPCRECT pRect,COLORREF cr);
        virtual HRESULT ClearRect(LPCRECT pRect,COLORREF cr);
        virtual HRESULT InvertRect(LPCRECT pRect);

        virtual HRESULT DrawEllipse(LPCRECT pRect);
        virtual HRESULT FillEllipse(LPCRECT pRect);
        virtual HRESULT FillSolidEllipse(LPCRECT pRect,COLORREF cr);

        virtual HRESULT DrawArc(LPCRECT pRect,float startAngle,float sweepAngle,bool useCenter);
        virtual HRESULT FillArc(LPCRECT pRect,float startAngle,float sweepAngle);

        virtual HRESULT DrawRoundRect(LPCRECT pRect,POINT pt);
        virtual HRESULT FillRoundRect(LPCRECT pRect,POINT pt);
        virtual HRESULT FillSolidRoundRect(LPCRECT pRect,POINT pt,COLORREF cr);

        virtual HRESULT DrawLines(LPPOINT pPt,size_t nCount);
        virtual HRESULT GradientFill(LPCRECT pRect,BOOL bVert,COLORREF crBegin,COLORREF crEnd,BYTE byAlpha=0xFF);
        virtual HRESULT GradientFillEx( LPCRECT pRect,const POINT* pts,COLORREF *colors,float *pos,int nCount,BYTE byAlpha=0xFF );

        virtual HRESULT TextOut(
            int x,
            int y,
            LPCTSTR lpszString,
            int nCount);

        virtual HRESULT DrawIconEx(int xLeft, int yTop, HICON hIcon, int cxWidth,int cyWidth,UINT diFlags);
        virtual HRESULT DrawBitmap(LPCRECT pRcDest,IBitmapPtr pBitmap,int xSrc,int ySrc,BYTE byAlpha=0xFF);
        virtual HRESULT DrawBitmapEx(LPCRECT pRcDest,IBitmapPtr pBitmap,LPCRECT pRcSrc,UINT expendMode, BYTE byAlpha=0xFF);
        virtual HRESULT DrawBitmap9Patch(LPCRECT pRcDest,IBitmapPtr pBitmap,LPCRECT pRcSrc,LPCRECT pRcSourMargin,UINT expendMode,BYTE byAlpha=0xFF);

        virtual IRenderObjPtr GetCurrentObject(OBJTYPE uType);
        virtual HRESULT SelectDefaultObject(OBJTYPE objType, IRenderObjPtr &ppOldObj);
        virtual HRESULT SelectObject(IRenderObjPtr pObj,IRenderObjPtr &ppOldObj);


        virtual COLORREF GetTextColor()
        {
            return m_curColor.toCOLORREF();
        }

        virtual COLORREF SetTextColor(COLORREF color)
        {
            COLORREF crOld=m_curColor.toCOLORREF();
            m_curColor.setRGB(color);
            ::SetTextColor(m_hdc,color&0x00ffffff);
            return crOld;
        }

		virtual void SetMaskFilter(IMaskFilterPtr pMaskFilter){}
		virtual IMaskFilterPtr GetMaskFilter(){return NULL;}

        virtual HDC GetDC(UINT uFlag=0);
        virtual void ReleaseDC(HDC hdc);

        virtual HRESULT SetTransform(const float matrix[9], float oldMatrix[9]);

        virtual HRESULT GetTransform(float matrix[9]) const;

		virtual COLORREF GetPixel( int x, int y );

		virtual COLORREF SetPixel( int x, int y, COLORREF cr );

		virtual HRESULT GradientFill2(LPCRECT pRect,GradientType type,COLORREF crStart,COLORREF crCenter,COLORREF crEnd,float fLinearAngle,float fCenterX,float fCenterY,int nRadius,BYTE byAlpha=0xff);

		virtual HRESULT CreateRegion( IRegionPtr &ppRegion );

		virtual HRESULT PushClipPath(const IPathPtr path, UINT mode, bool doAntiAlias = false);

		virtual HRESULT DrawPath(const IPathPtr path,IPathEffectPtr pathEffect=NULL);

		virtual HRESULT FillPath(const IPathPtr path);

		virtual HRESULT PushLayer(const RECT *pRect,BYTE byAlpha);

		virtual HRESULT PopLayer();

		virtual HRESULT SetXfermode(int mode,int *pOldMode);
		virtual BOOL SetAntiAlias(BOOL bAntiAlias);
	protected:
        HDC               m_hdc;
        SColor            m_curColor;
        SBitmap_GDIPtr    m_curBmp;
        SPen_GDIPtr       m_curPen;
        SBrush_GDIPtr     m_curBrush;
        SFont_GDIPtr      m_curFont;
        POINT             m_ptOrg;
        
        //注意保存4个默认的GDI对象
        IBitmapPtr        m_defBmp;
        IPenPtr           m_defPen;
        IBrushPtr         m_defBrush;
        IFontPtr          m_defFont;
        IRenderFactoryPtr m_pRenderFactory;
        UINT m_uGetDCFlag;
    };
    
    namespace RENDER_GDI
    {
        extern BOOL SCreateInstance(IRenderFactoryPtr &ppRenderFactory);
    }
}


